<?php
/**
 * Created by PhpStorm.
 * User: DaibiDaddy
 * Date: 2016/5/24
 * Time: 17:14
 */

namespace Base;

use BaseExt\Pagination;
use Doctrine\DBAL\Query\QueryBuilder;
use Doctrine\ORM\EntityManager;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;

class BaseController extends Controller {

    public function jumpToRoute($route)
    {
        header("location:".$this->generateUrl($route));exit;
    }
    public function jumpToURL($url)
    {
        header("location:$url");exit;
    }

    public function adminChkLogin()
    {
        $user = $this->getUser();
        is_object($user);
        if (is_object($user) && $uid = $user->getId()) {
            return $uid;
        } else {
            $this->jumpToRoute("adminLoginPage");
//            header("location:".$this->generateUrl("adminLoginPage"));exit;
        }
    }

    public function checkUserLogin()
    {
        $user = $this->getUser();
        is_object($user);
        if (is_object($user) && $uid = $user->getId()) {
            return $uid;
        } else {
            return false;
        }
    }

    /**
     * json 格式输出结果
     * @param $status
     * @param $info
     * @param array $data
     * @return Response
     */
    public function json_out ($status,$info,$data = array())
    {

        $data = array(
            "s"=> $status?$status:0,
            "i"  => $info?$info:"",
            "d"  => $data?$data:"",
        );
        return new Response(json_encode($data),200,array("content-type"=>"application/json"));
    }

    /**
     * js弹窗提示结果后跳转
     * @param $msg
     * @param $path
     * @return Response
     */
    public function js_out($msg,$path = "javascript:history.go(-1);")
    {
        $data = array(
            "url"   => $path,
            "msg"   => $msg,
        );
        return $this->render("SystemAdminBundle:Admin:message.html.twig",$data);
    }

    /**
     * js弹窗提示结果后跳转
     * @param $msg
     * @param $path
     * @return Response
     */
    public function msg_out($msg,$path = "")
    {
        $data = array(
            "url"   => $path,
            "msg"   => $msg,
        );
        return $this->render("SystemAdminBundle:Admin:msg.html.twig",$data);
    }

    /**
     * js弹窗提示结果后跳转
     * @param $msg
     * @param $path
     * @return Response
     */
    public function js_out_close($msg,$path = "javascript:window.close();")
    {
        $data = array(
            "url"   => $path,
            "msg"   => $msg,
        );
        return $this->render("SystemAdminBundle:Admin:message.html.twig",$data);
    }

    /**
     * 获取必填参数
     * @param $paramName
     * @return bool|mixed
     */
    public function getParamRequired($paramName)
    {
        $request = Request::createFromGlobals();
        if ($request->request->has("$paramName")) {
            return $request->get("$paramName");
        }
        if ($request->query->has("$paramName")) {
            return $request->get("$paramName");
        }
        return false;
    }

    /**
     * @param $base_url
     * @param $total_rows
     * @param int $per_page
     * @return array
     */
    public function creatPage($base_url,$total_rows,$per_page = 10)
    {
        $config['first_url'] = $base_url;
        $config['base_url'] = $base_url;
        $config['total_rows'] = $total_rows;
        $config['per_page'] = $per_page;
//        $config['reuse_query_string'] = TRUE;
//        $config["query_string_segment"] = "page";

        //分页基础配置
        $config['num_links'] = 3;
        $config['first_link'] = '首页';
        $config['prev_link'] = '«上一页';
        $config['cur_tag_open'] = '<span class="current">';
        $config['cur_tag_close'] = '</span>';
        $config['next_link'] = '下一页»';
        $config['last_link'] = '末页';

        $pageBuilder = new Pagination($config);
        $page =  $pageBuilder->create_links();
        return array(
            "total"     => $total_rows,
            "perPage"   => $per_page,
            "page"      => $page
        );
    }


    public function createMyForm($FBNameSpace , $entity , $actionUrl = "" , $method = "POST")
    {
        $config = array(
            "entity"   => $entity,
            "actionUrl"   => $actionUrl,

        );
        $options = array(
            "attr"  => array(
                "action" => $actionUrl,
                "method" => $method,
            ),
        );

        $form = $this->createFormBuilder($config["entity"],$options)->getForm();
        $m = $this->getDoctrine()->getManager();
        $formRows = new $FBNameSpace($m);
        foreach ($formRows->formConfig() as $key => $param) {
            $form->add($key,$this->type2RealType($param["showType"]),$this->basicParam($param["showType"],$param["label"],$param["dataType"],$param["option"]));
        }
        return $form;
    }

    private function type2RealType($type)
    {
        switch ($type) {
            case "article":
                $realType = "textarea";
                break;
            case "select":
                $realType = "choice";
                break;
            case "radio":
                $realType = "choice";
                break;
            case "checkbox":
                $realType = "choice";
                break;
            case "pic":
                $realType = "search";
                break;
            case "pics":
                $realType = "search";
                break;
            case "datetime":
            case "time":
            case "date":
                $realType = "text";
                break;
            default:
                $realType = $type;

        }
        return $realType;
    }

    public function basicParam($type,$name,$dataType,$option)
    {
        $attr = isset($option["attr"])?$option["attr"]:array();
        $attr = array_merge($attr,array("datatype"=>$dataType));
        $otherParam = isset($option["other"])?array_merge(array("label"=>$name),$option["other"]):array("label"=>$name);
        switch ($type) {
            case "select"://选择
                $basic = array_merge(array(
                    "attr"  => array_merge(array(
                        "class" => "rule-single-select",
                    ),$attr),
                    "expanded"=>"0",
                    "multiple"=>"0",
                ),$otherParam);
                return $basic;
                break;
            case "radio"://单选
                $basic = array_merge(array(
                    "attr"  => array_merge(array(
                        "class" => "rule-multi-radio",
                    ),$attr),
                    "expanded"=>"1",
                    "multiple"=>"0",
                ),$otherParam);
                return $basic;
                break;
            case "checkbox"://多选
                $basic = array_merge(array(
                    "attr"  => array_merge(array(
                        "class" => "rule-multi-checkbox",
                    ),$attr),
                    "expanded"=>"1",
                    "multiple"=>"1",
                ),$otherParam);
                return $basic;
                break;
            case "article"://富文本
                $basic = array_merge(array(
                    "attr"  => array_merge(array(
                        "class" => "editor",
                    ),$attr),
                    "required"  => False
                ),$otherParam);
                return $basic;
                break;
            case "date"://时间
                $basic = array_merge(array(
                    "attr"  => array_merge(array(
                        "class"=>"input rule-date-input" ,
                        'onfocus'=>"WdatePicker({dateFmt:'yyyy-MM-dd'})" ,
                        'datatype'=>"/^\s*$|^\d{4}\-\d{1,2}\-\d{1,2}$/" ,
                        'errormsg'=>"请选择正确的日期",
                    ),$attr)
                ),$otherParam);
                return $basic;
                break;
            case "time"://时间
                $basic = array_merge(array(
                    "attr"  => array_merge(array(
                        "class"=>"input rule-date-input" ,
                        'onfocus'=>"WdatePicker({dateFmt:'HH:mm:ss'})" ,
                        'datatype'=>"/^(\d{1,2}:){2}\d{1,2}$/" ,
                        'errormsg'=>"请选择正确的日期",
                    ),$attr)
                ),$otherParam);
                return $basic;
                break;
            case "datetime"://时间
                $basic = array_merge(array(
                    "attr"  => array_merge(array(
                        "class"=>"input rule-date-input" ,
                        'onfocus'=>"WdatePicker({dateFmt:'yyyy-MM-dd HH:mm:ss'})" ,
                        'datatype'=>"/^\s*$|^\d{4}\-\d{1,2}\-\d{1,2}\s{1}(\d{1,2}:){2}\d{1,2}$/" ,
                        'errormsg'=>"请选择正确的日期",
                    ),$attr)
                ),$otherParam);
                return $basic;
                break;
            default:
                $basic = array_merge(array(
                    "attr"  => array_merge(array(
                        //nothing
                    ),$attr),
                    "required"  => False
                ),$otherParam);
                return $basic;
        }
    }
    /*项目通用化增删改查*/
    private $entitySetting ;

    public function setSetting($entitySetting)
    {
        $this->entitySetting = $entitySetting;
    }

    public function comAdd( $entity = null)
    {
        if (!$entity) {
            $entity = new $this->entitySetting->entityPath();
        }
        $form = $this->createMyForm($this->entitySetting->SettingPath, $entity,   $this->generateUrl($this->entitySetting->entityName."DoAdd"));
        $show = $form->createView();
        $entityCnName = $this->entitySetting->entityCnName;
        $data = array(
            "title" => "新增$entityCnName",
            "submitUrl" => $this->generateUrl($this->entitySetting->entityName."DoAdd"),
            "submitType" => "Post",
            "show"   => $show,
        );
        return $this->render($this->entitySetting->bundleName.":".$this->entitySetting->entityName.":add.php.twig",$data);
    }

    public function comDoAdd($request , $entity = null)
    {
        if (!$entity) {
            $entity = new $this->entitySetting->entityPath();
        }
        $form = $this->createMyForm($this->entitySetting->SettingPath,  $entity);
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($entity);
            $em->flush();
            return $this->redirectToRoute($this->entitySetting->entityName.'Lists');
        } else {
            return $this->js_out("系统错误，请联系管理员",$this->generateUrl($this->entitySetting->entityName."PreAdd"));
        }
    }

    public function comEdit($entity)
    {
        $action = $this->generateUrl($this->entitySetting->entityName."DoEdit",array("id"=>$entity->getId()));
        $form = $this->createMyForm($this->entitySetting->SettingPath,  $entity ,  $action );
        $show = $form->createView();
        $entityCnName = $this->entitySetting->entityCnName;
        $data = array(
            "title" => "管理$entityCnName",
            "submitUrl" => $this->generateUrl($this->entitySetting->entityName."DoAdd"),
            "submitType" => "Post",
            "show"   => $show,
        );
        return $this->render($this->entitySetting->bundleName.":".$this->entitySetting->entityName.":add.php.twig",$data);
    }

    public function comDoEdit(Request $request, $entity)
    {
        $form = $this->createMyForm($this->entitySetting->SettingPath,  $entity );
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($entity);
            $em->flush();
            return $this->redirectToRoute($this->entitySetting->entityName.'Lists');
        } else {
            return $this->js_out("系统错误，请联系管理员",$this->generateUrl($this->entitySetting->entityName."PreEdit",array("id"=>$entity->getId())));
        }
    }

    public function comLists($tools)
    {
        /*分页配置*/
        if (!$page   = $this->getParamRequired("page")) { $page = 1;}
        $per_page   = $this->entitySetting->perPage;
        $lists = $this->getLists($page,$per_page);
        $total = $lists["total"];

        /*URL配置*/
        $urls = array(
            "toolUrl"=>$this->generateUrl($this->entitySetting->entityName."Tools"),
            "addUrl"=>$this->generateUrl($this->entitySetting->entityName."PreAdd"),
        );


        $entityCnName = $this->entitySetting->entityCnName;
        return $this->render($this->entitySetting->bundleName.":".$this->entitySetting->entityName.":list.php.twig", array(
            'title'     => "$entityCnName 列表",
            "tools"   => $tools,
            'urls'      => $urls,
            'lists'     => $lists["data"],
            'page'      => $this->creatPage($this->generateUrl($this->entitySetting->entityName."Lists"),$total,$per_page),
        ));
    }



    public function comCatLists()
    {
        $lists = $this->getLists(0,0);
        $data = $this->buildeCatTree($lists["data"],$this->entitySetting->table);
        /*URL配置*/
        $urls = array(
            "toolUrl"=>$this->generateUrl($this->entitySetting->entityName."Tools"),
            "addUrl"=>$this->generateUrl($this->entitySetting->entityName."PreAdd"),
        );
        $rep = $this->getDoctrine()->getManager()->getRepository($this->entitySetting->bundleName.":".$this->entitySetting->entityName);
        $classes = $rep->findAll();

        $entityCnName = $this->entitySetting->entityCnName;
        return $this->render($this->entitySetting->bundleName.":".$this->entitySetting->entityName.":cat_list.php.twig", array(
            'title'     => "$entityCnName 列表",
            "classes"   => $classes,
            'urls'      => $urls,
            'lists'     => $data,
        ));
    }

    public function buildeCatTree($data,$table = "")
    {
        if ($table) {
            $table = $table."_";
        }
        $newData = array();
        foreach ($data as $d) {//根据parent取出子项
            $newData[$d[$table."id"]] = $d;
        }
        $groupByParent = array();
        foreach ($newData as $d) {//根据parent取出子项
            $groupByParent[$d[$table."parent"]][$d[$table."orders"]*1000000 + $d[$table."id"]] = $d;
        }

        $curParent = 0;
        $isEnd = 0;
        $sortedArray = array();
        $i = 0;
        if (isset($groupByParent[$curParent])) {
            do {
                ksort($groupByParent[$curParent]);
                if (isset($groupByParent[$curParent])) {//此ID下有分类
                    //设置这个父元素的相邻父元素
                    $first = reset($groupByParent[$curParent]);
                    //取出当前分组的第一个元素并删除
                    $sortedArray[] = $first;
                    array_shift($groupByParent[$curParent]);
                    if (isset($groupByParent[$first[$table."id"]])) {//查找子元素
                        $curParent = $first[$table."id"];
                    }else{//子元素没有的时候需要检测时候还有兄弟元素
                        while(empty($groupByParent[$curParent])) {
                            unset($groupByParent[$curParent]);
                            if ($curParent == 0) {
                                $isEnd = 1;
                                break;
                            }
                            $curParent = $newData[$curParent][$table."parent"];
                        }
                    }
                    if ($isEnd) {break;}
                }
                $i ++ ;
            } while (count($sortedArray) < count($newData) && $i < 100);
        } else {
            $sortedArray = $newData;
        }
        return $sortedArray;
    }

    public function getLists($page,$per_page)
    {
        $modelPath = $this->entitySetting->modelPath;

        $model = new $modelPath($this->getDoctrine());
        $params = array();

        $request = Request::createFromGlobals();
        $txtKeywords = $request->get("txtKeywords");
        if ( $condition = $request->get("cond") ) {
            foreach ( $condition as $key => $val ) {
                if ($val === "") {
                    continue;
                }
                $params["conditions"][$this->entitySetting->table][$key]["eq"]=$val;
            }
        }

        if ($txtKeywords) {
            $params["textKey"] = "%$txtKeywords%";
        }
        $params["orderBy"][$this->entitySetting->table]["id"]="DESC";
        $params["groupBy"][$this->entitySetting->table]=array("id");
        $rst = $model->getAdminLists($params,$page * $per_page - $per_page,$per_page);
        return $rst;
    }

    public function comTools(Request $request)
    {
        if($__EVENTTARGET = $this->getParamRequired("__EVENTTARGET")){
            unset($_GET['__EVENTTARGET']);
        }else{
            return $this->js_out("参数丢失",$this->redirectToRoute($this->entitySetting->entityName."Lists"));
        }
        if($__EVENTARGUMENT = $this->getParamRequired("__EVENTARGUMENT")){
            unset($_GET['__EVENTARGUMENT']);
        }
        $em = $this->getDoctrine()->getManager();
        //如果是删除操作执行删除操作
        if ($__EVENTTARGET == "multiDelete") {
            if($ids = $this->getParamRequired("ids")){
                unset($_GET['ids']);
            }else{
                return $this->js_out("参数丢失",$this->redirectToRoute($this->entitySetting->entityName."Lists"));
            }
            if (is_array($ids) && !empty($ids)) {
                foreach ($ids as $id) {
                    $entity  = $em->find($this->entitySetting->bundleName.":".$this->entitySetting->entityName,$id);
                    $em->remove($entity);
                }
                $em->flush();
            }
        }
        //如果是修改操作执行修改操作
        if ($__EVENTTARGET == "setAttr") {
            parse_str($__EVENTARGUMENT,$data);
            if (is_array($data) && isset($data["id"])) {
                $entity  = $em->find($this->entitySetting->bundleName.":".$this->entitySetting->entityName,$data["id"]);
                unset($data["id"]);
                foreach ($data as $key => $val) {
                    if ( !in_array( $key , $this->entitySetting->editKeys ) ) { continue; }
                    $func = "set$key";
                    $entity->$func($val);
                }
                $em->persist($entity);
                $em->flush();
            }
        }
        //否则将参数传递至list
        $cond["cond"] = $request->get("cond");
        $queryStr = http_build_query($cond);
        if ($txtKeywords = $request->get("txtKeywords")) {
            $queryStr .= "&txtKeywords=".$txtKeywords;
        }
        return $this->redirect($this->generateUrl($this->entitySetting->entityName."Lists")."?".$queryStr);
    }


    public function updateUserSession($userInfo)
    {
        $userSession = array(
            "uid"       => $userInfo["id"],
            "groups"    => $userInfo["groups"],
            "level"     => $userInfo["level"],
            "account"   => $userInfo["account"],
        );
        $session = $this->container->get("session");
        foreach ($userSession as $key => $val) {
            $session->set($key,$val);
        }
    }

    public function log_out($info)
    {
        $logger = $this->get("logger");
        $logger->info(json_encode($info));
    }
}
